package mirrormonkey.core.server;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

import mirrormonkey.core.EntityLifecycleListener;
import mirrormonkey.framework.ConnectionInfo;
import mirrormonkey.framework.ServerSyncAppState;

import com.jme3.network.ConnectionListener;
import com.jme3.network.HostedConnection;
import com.jme3.network.MessageConnection;
import com.jme3.network.Server;

public class ServerConnectionInfo extends ConnectionInfo implements
		ConnectionListener {

	private final ServerCoreModule module;

	private final Map<Integer, MappingStack> entities;

	public ServerConnectionInfo(ServerSyncAppState appState,
			MessageConnection connection) {
		super(appState, connection, false);
		module = appState.getModule(ServerCoreModule.class);
		entities = new HashMap<Integer, MappingStack>();
		appState.eventManager.addConnectionListener(this);
	}

	public void destroy() {
		while (!entities.isEmpty()) {
			entities.values().iterator().next().destroy();
		}
		Collection<EntityLifecycleListener> l = new LinkedList<EntityLifecycleListener>();
		getListenerConfiguration().getListeners(EntityLifecycleListener.class,
				l);
		for (EntityLifecycleListener i : l) {
			getListenerConfiguration().removeListener(i);
		}
		module.remove(connection);
		registered = false;
		running = false;
	}

	protected void addMapping(ServerEntityData entityData,
			ExistingMappingStack existingMappingStack) {
		if (!isRegistered()) {
			module.register(this);
			registered = true;
		}
		if (!isRunning()) {
			running = true;
		}
		entities.put(entityData.getId(), existingMappingStack);
	}

	protected void removeMapping(ServerEntityData entityData,
			ExistingMappingStack existingMappingStack) {
		entities.remove(entityData.getId());
		if (isRegistered() && entities.isEmpty()) {
			if (getListenerConfiguration().isEmpty()) {
				destroy();
			} else {
				running = false;
			}
		}
	}

	@Override
	public void addEntityLifecycleListener(EntityLifecycleListener listener) {
		if (!isRegistered()) {
			if (module.hasData(getConnection())) {
				throw new IllegalStateException();
			}
			module.register(this);
			registered = true;
		}
		super.addEntityLifecycleListener(listener);
	}

	@Override
	public void removeEntityLifecycleListener(EntityLifecycleListener listener) {
		if (!isRegistered() && module.hasData(getConnection())) {
			throw new IllegalStateException();
		}
		super.removeEntityLifecycleListener(listener);
		if (isRegistered() && getListenerConfiguration().isEmpty()) {
			if (entities.isEmpty()) {
				destroy();
			}
		}
	}

	@Override
	public void connectionAdded(Server server, HostedConnection conn) {
	}

	@Override
	public void connectionRemoved(Server server, HostedConnection conn) {
		System.out.println("CONNECTION REMOVED");
		if (conn.equals(connection)) {
			// prevent messages from being sent on destroy
			running = false;
			destroy();
		}
	}

}
